home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
comm
/
pccp019.zip
/
XMODEMR.C
< prev
next >
Wrap
Text File
|
1992-05-04
|
7KB
|
370 lines
/* Copyright (C) 1992 Peter Edward Cann, all rights reserved.
* MicroSoft QuickC: >qcl term.c graphics.lib
*/
#include<stdio.h>
#include<bios.h>
#include<dos.h>
#include<fcntl.h>
#include<sys\types.h>
#include<sys\stat.h>
#include<signal.h>
#define DLLSBREG 0
#define DLMSBREG 1
#define INTCTLREG 1
#define INTIDREG 2
#define LCTLREG 3
#define MCTLREG 4
#define STATREG 5
#define MSTATREG 6
#define CTSMASK 0x10
#define TXMTMASK 0x20
#define RXRDYMASK 0x01
#define INTACK 0x20
#define DB7 0x02
#define DB8 0x03
#define STOP2 0x04
#define PARITYEN 0x08
#define PARITYEVEN 0x10
#define DLAB 0x80
#define INTBASE1 0x20
#define INTMASK1 0x21
#define INTBASE2 0xa0
#define INTMASK2 0xa1
#define TBUFSIZ 256
#define NAK 21
#define ACK 6
#define SOH 1
#define EOT 4
#define CAN 24
int index, basereg;
unsigned char buf[TBUFSIZ];
unsigned char diffintmask, irqnum;
void (interrupt far *oldvect)();
void interrupt far inthndl(_es, _ds, _di, _si, _bp, _sp,
_bx, _dx, _cx, _ax, _ip, _cs, _flags)
unsigned _es, _ds, _di, _si, _bp, _sp;
unsigned _bx, _dx, _cx, _ax, _ip, _cs, _flags;
{
if(inp(basereg+STATREG)&RXRDYMASK)
{
buf[index++]=inp(basereg)&0xff;
index=index%TBUFSIZ;
}
outp(INTBASE1, INTACK);
outp(INTBASE2, INTACK);
}
sendchar(c)
unsigned char c;
{
while(!((inp(basereg+STATREG)&TXMTMASK)&&(inp(basereg+MSTATREG)&CTSMASK)));
outp(basereg, c);
}
int follow;
int rcharto(ticks)
int ticks;
{
long tstamp, tstamp1, dayofticksp;
int c;
_bios_timeofday(_TIME_GETCLOCK, &tstamp);
dayofticksp=0;
while(1)
{
if(_bios_timeofday(_TIME_GETCLOCK, &tstamp1))
dayofticksp+=20*60*60*24;
if(tstamp1+dayofticksp-tstamp>ticks)
return(-1); /* NOTE: This is an INT!!! */
if(follow!=index)
{
c=buf[follow++];
follow=follow%TBUFSIZ;
return(c);
}
}
}
unsigned char block[128];
rblock()
{
int i, blockn, invblockn, rchecksum, checksum;
checksum=0;
if((blockn=rcharto(20))==-1)
return(-1);
printf("Block %d: ", blockn);
if((invblockn=rcharto(20))==-1)
return(-1);
for(i=0;i<128;++i)
{
if((block[i]=rcharto(20))==-1)
return(-1);
checksum+=block[i];
checksum&=0xff;
}
if((rchecksum=rcharto(20))==-1)
return(-1);
if(((invblockn^0xff)&0xff)!=blockn)
{
printf("Bad complement block number.\n");
return(-1);
}
if(checksum!=rchecksum)
{
printf("Checksum mismatch. Here=%02x There=%02x.\n", checksum, rchecksum);
return(-1);
}
return(blockn);
}
unsigned intnum;
unsigned char oldintmask;
cleanup()
{
if(intnum==10)
outp(INTMASK2, oldintmask);
else
outp(INTMASK1, oldintmask);
outp(basereg+INTCTLREG, 0x00);
outp(basereg+MCTLREG, 0x03);
_dos_setvect(intnum, oldvect);
}
quit()
{
cleanup();
exit(99);
}
main(argc, argv)
int argc;
char **argv;
{
int i, j, outfd, ok, c;
long nbytes;
unsigned char newintmask, lctl, dlmsb, dllsb, blocknum;
unsigned speed;
int comnum;
char stopbits;
index=follow=0;
lctl=0;
printf("Copyright (C) 1992 Peter Edward Cann, all rights reserved.\n");
printf("xmodem checksum receive of %s.\n", argv[4]);
if(argc!=5)
{
printf("USAGE: xmodemr <comnum> <bps> <stopbits> <file pathname>\n");
exit(1);
}
if((outfd=open(argv[4], O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, S_IWRITE))==-1)
{
printf("Error opening file %s.\n", argv[4]);
exit(2);
}
comnum=atoi(argv[1])-1;
newintmask=0;
switch(comnum)
{
case 0:
irqnum=4;
diffintmask=0xff&~0x10;
basereg=0x3f8;
break;
case 1:
irqnum=3;
diffintmask=0xff&~0x08;
basereg=0x2f8;
break;
case 2:
irqnum=4;
diffintmask=0xff&~0x10;
basereg=0x3e8;
break;
case 3:
irqnum=3;
diffintmask=0xff&~0x08;
basereg=0x2e8;
break;
case 4:
irqnum=2;
diffintmask=0xff&~0x02;
basereg=0x3e8;
break;
case 5:
irqnum=2;
diffintmask=0xff&~0x02;
basereg=0x2e8;
break;
case 6:
irqnum=5;
diffintmask=0xff&~0x20;
basereg=0x3e8;
break;
case 7:
irqnum=5;
diffintmask=0xff&~0x20;
basereg=0x2e8;
break;
default:
printf("Bad port choice.\n");
exit(4);
}
intnum=irqnum+8;
speed=atoi(argv[2]);
switch(speed)
{
case 300:
dlmsb=0;
dllsb=0xc0;
break;
case 1200:
dlmsb=0;
dllsb=0x60;
break;
case 2400:
dlmsb=0;
dllsb=0x30;
break;
case 9600:
dlmsb=0;
dllsb=0x0c;
break;
case 19200:
dlmsb=0;
dllsb=0x06;
break;
case 38400:
dlmsb=0;
dllsb=0x03;
break;
case 57600:
dlmsb=0;
dllsb=0x02;
break;
default:
printf("Bad speed.\n");
exit(5);
}
lctl|=DB8;
stopbits=argv[3][0];
switch(stopbits)
{
case '1':
break;
case '2':
lctl|=STOP2;
break;
default:
printf("Bad stop bits.\n");
exit(9);
}
signal(SIGINT, quit);
outp(basereg+LCTLREG, DLAB);
outp(basereg+DLLSBREG, dllsb);
outp(basereg+DLMSBREG, dlmsb);
outp(basereg+LCTLREG, lctl);
oldvect=_dos_getvect(intnum);
_dos_setvect(intnum, inthndl);
outp(basereg+INTCTLREG, 0x00);
outp(basereg+MCTLREG, 0x0b);
oldintmask=(intnum==10)?inp(INTMASK2):inp(INTMASK1);
newintmask=diffintmask;
newintmask&=oldintmask;
if(intnum==10)
outp(INTMASK2, newintmask);
else
outp(INTMASK1, newintmask);
outp(INTBASE1, INTACK);
outp(INTBASE2, INTACK);
outp(basereg+INTCTLREG, 0x01);
outp(INTBASE1, INTACK);
outp(INTBASE2, INTACK);
ok=nbytes=0;
for(i=0;i<10;++i)
{
sendchar(NAK);
c=rcharto(200);
if(c==SOH)
{
ok=1;
break;
}
}
if(!ok)
{
printf("No SOH after 10 10-second-spaced NAKs.\n");
cleanup();
exit(10);
}
blocknum=1;
for(i=0;i<10;++i)
{
printf("\nSeeking block %d: ", blocknum);
if((c=rblock())==blocknum)
{
i=0;
if(write(outfd, block, 128)!=128)
{
printf("Write error.\n");
cleanup();
exit(13);
}
nbytes+=128;
printf("Successful. Bytes so far: %ld", nbytes);
blocknum=(blocknum+1)&0xff;
sendchar(ACK);
}
else
if(c==-1)
{
while(rcharto(20)!=-1);
sendchar(NAK);
}
else if(c<blocknum)
sendchar(ACK);
else
{
printf("\nSender skipped a block; cancelling transfer.\n");
for(j=0;j<10;++j)
sendchar(CAN);
cleanup();
exit(14);
}
do
c=rcharto(200);
while((c!=EOT)&&(c!=SOH)&&(c!=CAN)&&(c!=-1));
if(c==EOT)
{
sendchar(ACK);
printf("\nTransfer successful.\n");
close(outfd);
cleanup();
exit(0);
}
if(c!=SOH)
{
if(c==-1)
printf("Timeout waiting for SOH or EOT.\n");
else
printf("Spurrious character hex %02x; SOH or EOT expected.\n", c);
cleanup();
exit(11);
}
}
printf("Retry limit exceeded.\n");
cleanup();
exit(12);
}